Actuellement, le développement Web côté client (frontend) est très souvent réalisé en JavaScript ou dans des langages dérivés comme TypeScript. Il existe cependant d’autres outils intéressants, basés sur des langages de programmation fonctionnelle, qui permettent notamment d’éviter de nombreuses erreurs lors de l’exécution sur le navigateur.
L’objectif de cette dépêche est de rappeler quelques généralités sur le développement Web frontend, et de présenter les outils Elm, Purescript, Miso et Reflex, à partir d’un exemple d’application (galerie d’images fournie via une API Web).
Attention : ceci n’est pas une étude rigoureuse et avancée mais juste un petit retour de petite expérience.
Voir également le dépôt de code de l’exemple et une présentation en vidéo.
Sommaire
- Généralités sur le web frontend
- Un exemple de base
- Elm
- Purescript
- Haskell/Miso
- Haskell/Reflex
- Conclusion
Généralités sur le web frontend
Page web, application web, application native
Historiquement, les pages web se contentaient d'afficher un contenu statique et de proposer des liens vers d'autres pages. Des éléments dynamiques sont ensuite progressivement apparus : animations, formulaires avec vérifications de saisies… si bien, qu'aujourd'hui, de nombreuses pages web sont de véritables interfaces utilisateurs, comparables aux logiciels classiques installés sur le système. On appelle ce genre de pages des applications web (exécutées par un navigateur web), à distinguer des applications natives (exécutées par le système d'exploitation).
D'un point de vue utilisateur, les applications web et les applitions natives sont de plus en plus proches. Par exemple, on trouve des applition web de traitement de texte (frama-pad, google-docs) qui possèdent une bonne part des fonctionnalités de leurs équivalents natifs (libreoffice, msoffice).
D'un point de vue développeur, les technologies utilisées sont historiquement très différentes. Les applications natives utilisent généralement des langages comme Java, C#, Swift et leurs frameworks associés. Les applications web utilisent les technologies issues du web HTML/CSS/JavaScript et dépendent quasi-systématiquement d'un accès réseau via des websockets, requêtes AJAX ou autres. Cependant, on note une convergence web/natif également à ce niveau, notamment avec l'apparition du framework Electron, qui permet d'utiliser des technologies web pour développer des applications natives. De même, des architectures logicielles comme le Modèle-Vue-Contrôleur, très courant en natif, a été repris dans de nombreux frameworks web.
Les langages pour le web frontend
Le langage des applis web est sans conteste le JavaScript. C'est un langage assez controversé mais qui a tout de même des avantages indéniables, surtout depuis les récentes normes (ES2015…) : flexibilité, expressivité, compilateurs Just-In-Time performants, intégration dans les navigateurs…
Cependant, JavaScript permet facilement de faire des erreurs qui se produiront à l'exécution finale de l'application, les fameuses runtime errors. Pour éviter ces erreurs, on utilise souvent des outils comme des analyseurs statiques, debuggers ou tests unitaires. Une autre solution consiste à utiliser des frameworks (Angular, React…), des bibliothèques (Immutable, Redux…) voire des langages dérivés (TypeScript…) qui réduisent les sources d'erreurs possibles.
Les langages fonctionnels pour le web frontend
En fait, une bonne partie des solutions proposées pour rendre le développement en JavaScript plus robuste existe déjà naturellement dans des langages fonctionnels comme Haskell : immuabilité, fonctions pures, typage statique fort… Certains développeurs se sont donc naturellement inspirés des langages fonctionnels pour proposer des technos web frontend garantissant l'absence d'erreurs au runtime.
L'idée de ces technos est de fournir un écosystème complet (langage fonctionnel, compilateur, bibliothèques…) adapté au web et produisant du code JavaScript exécutable par un navigateur. Parmi ces technos, on trouve Elm et Purescript, qui proposent des langages inspirés d'Haskell. Il est également possible d'utiliser directement le langage Haskell (éventuellement avec des bibliothèques comme Miso ou Reflex) et le compilateur Ghcjs pour produire du code JavaScript. Enfin, il existe des outils dans d'autres langages fonctionnels comme ClojureScript, Ocsigen (OCaml)…
Les concepts de MVC, FRP, Virtual-DOM
Ces trois concepts sont généralement au cœur des technos web frontend fonctionnelles. Ils sont également assez fréquents dans l'écosystème JavaScript classique.
Le MVC (Model-View-Controler) est une architecture de code qui permet d'organiser une application en trois parties : le modèle (données « métier » à manipuler), la vue (affichage présenté à l'utilisateur) et le contrôleur (mise à jour de l'application en fonction des événements). Généralement, un MVC gére les événements de façon asynchrone et unidirectionnelle : les événements de la vue sont passés au contrôleur, qui modifie le modèle puis lance un rafraichissement de la vue…
Le FRP (Functional Reactive Programming) est le principe de base des frameworks fonctionnels, sur lequel est implémenté le MVC. Le FRP permet d'implémenter le comportement dynamique des interfaces utilisateur. Il traite les flux d'événements au cours du temps et transmet ces flux entre les différents composants de l'application, le tout de façon fonctionnelle (sans effet de bord).
Enfin, un concept essentiel aux applications web est le DOM virtuel. Le DOM (Document-Object-Model) décrit la structure d'une page web, donc de l'application, dans le navigateur. Au cours de son exécution, une appli web a besoin de manipuler le DOM, pour récupérer des données ou pour modifier l'affichage. Or, manipuler directement le DOM est coûteux et résulte en une application peu réactive. Pour améliorer les performances, les frameworks web utilisent un système de cache, le DOM virtuel, qui regroupe des modifications et ainsi minimise les accès au DOM.
Un exemple de base
Pour illustrer les outils de web frontend fonctionnel, imaginons qu'on veuille implémenter une appli client-serveur de recherche et d'affichage d'images d'animaux. Le serveur fournit les images en HTTP à l'URL /img/<nom-du-fichier>
. Il fournit également une API JSON à l'URL /api/animals <prefix>
auquel il répond par la liste des animaux de sa base de données dont le type correspond au préfixe donné en paramètre. Chaque élément de la liste retournée contient le type de l'animal et le nom du fichier image (accessible via l'URL /img
). Si aucun préfixe n'est donné, le serveur retourne la liste complète.
L'appli web client à réaliser contient simplement une zone de texte permettant de saisir le préfixe. Il envoie des requêtes AJAX au serveur pour récupérer les animaux correspondant puis affiche les images correspondantes après les avoir également demandées au serveur.
Ci-dessous une image du client implémenté en Purescript. L'ensemble du code est disponible sur ce dépôt git.
Elm
Elm est un environnement complet de développement web frontend fonctionnel. Il fournit un langage fonctionnel (inspiré d'Haskell mais en beaucoup plus simple), un compilateur Elm vers JavaScript et des bibliothèques. Elm est basé sur un DOM virtuel performant et permet de développer des applis web selon une architecture MVC.
Ci-dessous une implémentation en Elm de l'application d'exemple (note pour les développeurs Elm : désolé pour le non-respect des règles de formatage de code Elm mais j'ai subi des pressions de la part de la ligue de protection des molettes de souris). Ce code suit un schéma MVC et un style fonctionnel très classique. On définit un type Animal
, avec ses fonctions de décodage de données JSON, ainsi que le modèle de l'application, c'est-à-dire simplement la liste des Animal
à afficher.
Au niveau du contrôleur, le type Msg
définit les événements qui peuvent se produire. L'événement MsgInput
modélise une action de l'utilisateur sur la zone de texte et l'événement MsgAnimals
un message du serveur transmettant les Animal
en réponse à une requête à l'API. Ces événements sont gérés dans la fonction update
: MsgInput
ne change pas le modèle mais lance une requête à l'API via la fonction queryAnimals
, MsgAnimals
met à jour le modèle avec les données Animal
reçues.
Enfin, la fonction view
indique comment construire la vue de l'appli, à partir du modèle : un titre h1
, une zone de texte input
puis un div
pour chaque Animal
du modèle.
module Main exposing (..)
import Html exposing (..)
import Html.Attributes exposing (height, href, src, width)
import Html.Events exposing (onClick, onInput)
import Http
import Json.Decode as JD
main : Program Never Model Msg
main = Html.program
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}
-- Model
type alias Animal =
{ animalType : String
, animalImage : String
}
decodeAnimal : JD.Decoder Animal
decodeAnimal = JD.map2 Animal
(JD.field "animalType" JD.string)
(JD.field "animalImage" JD.string)
decodeAnimalList : JD.Decoder (List Animal)
decodeAnimalList = JD.list decodeAnimal
type alias Model = { modelAnimals : List Animal }
init : ( Model, Cmd Msg )
init = ( Model [], queryAnimals "" )
-- Controler
subscriptions : Model -> Sub Msg
subscriptions _ = Sub.none
type Msg
= MsgInput String
| MsgAnimals (Result Http.Error (List Animal))
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
MsgInput animalType -> ( model, queryAnimals animalType )
MsgAnimals (Ok Model animals) -> ( Model animals, Cmd.none )
MsgAnimals (Err _) -> ( Model [], Cmd.none )
queryAnimals : String -> Cmd Msg
queryAnimals txt =
let url = "http://localhost:3000/api/animals/" ++ txt
in Http.send MsgAnimals (Http.get url decodeAnimalList)
-- View
view model =
span [] [ h1 [] [ text "Animals (Elm)" ]
, p [] [ input [ onInput MsgInput ] [] ]
, span []
(List.map
(\a -> div [] [ p [] [ text a.animalType ]
, img
[ src ("http://localhost:3000/img/" ++ a.animalImage)
, height 240
, width 320
]
[]
]
) model.modelAnimals
)
]
Elm a l'avantage d'être particulièrement simple à utiliser. Les applis développées suivent toujours un MVC bien définis et les messages du compilateur sont particulièrement clairs. Le code JavaScript produit est léger et performant. Parmi les inconvénients, on peut noter que Elm est limité au schéma MVC qui, bien que très répandu, ne sera peut-être pas adapté à toutes les applications.
Purescript
Purescript est également un environnement complet (langage, compilateur, bibliothèques) mais plus général que Elm. En effet, son langage est plus proche d'Haskell et plus puissant (il supporte notamment les classes de type). De plus, Purescript propose différentes architecture de code, dont MVC. Enfin, Purescript peut être également utilisé pour le développement côté serveur.
Ci-dessous une implémentation en Purescript de l’application d’exemple, utilisant la bibliothèque Halogen (FRP + DOM virtuel). Ce code est très proche du code Elm. Pour le modèle, on définit également un type Animals
, avec les fonctions de décodage JSON, et un type Model
. Pour le contrôleur, on définit un type Query
qui permet de gérer la requête AJAX et sa réponse, via la fonction eval
. Enfin, la vue suit le même schéma que l'implémentation en Elm.
module Main where
import Control.Monad.Aff (Aff)
import Control.Monad.Eff (Eff)
import Data.Argonaut ((.?), class DecodeJson, decodeJson, Json)
import Data.Either (Either(..))
import Data.Maybe (Maybe(..))
import Data.Traversable (traverse)
import Halogen as H
import Halogen.Aff as HA
import Halogen.HTML as HH
import Halogen.HTML.Events as HE
import Halogen.HTML.Properties as HP
import Halogen.VDom.Driver (runUI)
import Network.HTTP.Affjax as AX
import Prelude
main :: Eff (HA.HalogenEffects (ajax :: AX.AJAX)) Unit
main = HA.runHalogenAff do
body <- HA.awaitBody
io <- runUI ui unit body
io.query $ H.action $ QueryAnimals ""
ui :: forall eff. H.Component HH.HTML Query Unit Void (Aff (ajax :: AX.AJAX | eff))
ui = H.component
{ initialState: const initialState
, render
, eval
, receiver: const Nothing
}
-- Model
newtype Animal = Animal
{ animalType :: String
, animalImage :: String
}
instance decodeJsonBlogPost :: DecodeJson Animal where
decodeJson json = do
obj <- decodeJson json
animalType <- obj .? "animalType"
animalImage <- obj .? "animalImage"
pure $ Animal { animalType, animalImage }
decodeAnimalArray :: Json -> Either String (Array Animal)
decodeAnimalArray json = decodeJson json >>= traverse decodeJson
type Model = { modelAnimals :: Array Animal }
initialState :: Model
initialState = { modelAnimals: [] }
-- Controler
data Query a = QueryAnimals String a
eval :: forall eff. Query ~> H.ComponentDSL Model Query Void (Aff (ajax :: AX.AJAX | eff))
eval (QueryAnimals animal_type next) = do
H.modify (_ { modelAnimals = [] })
response <- H.liftAff $ AX.get ("http://localhost:3000/api/animals/" <> animal_type)
let animals = case decodeAnimalArray response.response of
Left _ -> []
Right ra -> ra
H.modify (_ { modelAnimals = animals })
pure next
-- View
render :: Model -> H.ComponentHTML Query
render m =
HH.span []
[ HH.h1 [] [ HH.text "Animals (Purescript)" ]
, HH.p [] [ HH.input [ HE.onValueInput (HE.input QueryAnimals) ] ]
, HH.span []
(map (\ (Animal {animalType, animalImage})
-> HH.div []
[ HH.p [] [ HH.text animalType ]
, HH.img [ HP.src ("http://localhost:3000/img/" <> animalImage)
, HP.width 320
, HP.height 240
]
]
) m.modelAnimals)
]
Purescript a l'avantage d'être plus puissant et plus général que Elm. En contrepartie, il est moins simple à utiliser. Son environnement est également plus compliqué à utiliser : il faut gérer les dépendances Purescript avec bower
, les dépendances nodejs avec npm
et la compilation avec pulp
.
Haskell/Miso
Miso est une bibliothèque Haskell pour développer des applis web frontend. Miso permet de coder une appli MVC + DOM virtuel et de la compiler en JavaScript grâce à Ghcjs.
Ci-dessous une implémentation en Haskell + Miso de l’application d’exemple. Ce code est très similaire à l'implémentation en Elm. Miso annonce d'ailleurs explicitement s'inspirer de Elm.
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
import Data.Aeson (FromJSON, decodeStrict)
import Data.Maybe (fromMaybe)
import Data.Monoid ((<>))
import Data.Text (Text)
import GHC.Generics (Generic)
import JavaScript.Web.XMLHttpRequest (Request(..), RequestData(..), Method(..), contents, xhrByteString)
import Miso
import Miso.String (MisoString, toMisoString, fromMisoString, pack)
main :: IO ()
main = startApp App
{ model = Model []
, update = updateModel
, view = viewModel
, subs = []
, events = defaultEvents
, initialAction = GetAnimals ""
, mountPoint = Nothing
}
-- Model
data Animal = Animal
{ animalType :: Text
, animalImage :: Text
} deriving (Eq, Generic, Show)
instance FromJSON Animal
data Model = Model { modelAnimals :: [Animal] } deriving (Eq, Show)
-- Controler
data Action
= GetAnimals MisoString
| SetAnimals [Animal]
| NoOp
deriving (Show, Eq)
updateModel :: Action -> Model -> Effect Action Model
updateModel (GetAnimals str) m = m <# (SetAnimals <$> queryAnimals str)
updateModel (SetAnimals animals) m = noEff m { modelAnimals = animals }
updateModel NoOp m = noEff m
queryAnimals :: MisoString -> IO [Animal]
queryAnimals str = do
let uri = pack $ "http://localhost:3000/api/animals/" ++ fromMisoString str
req = Request GET uri Nothing [] False NoData
Just cont <- contents <$> xhrByteString req
return $ fromMaybe [] $ decodeStrict cont
-- View
viewModel :: Model -> View Action
viewModel (Model animals) =
span_ []
[ h1_ [] [ text "Animals (Miso)" ]
, p_ [] [ input_ [ onInput GetAnimals ] ]
, span_ [] $ map fmtAnimal animals
]
fmtAnimal :: Animal -> View Action
fmtAnimal animal =
div_ []
[ p_ [] [ text $ toMisoString $ animalType animal ]
, img_ [ src_ $ toMisoString $ "http://localhost:3000/img/" <> animalImage animal
, width_ "320"
, height_ "240"
]
]
Pour un développeur Haskell, Miso est une bibliothèque intéressante, car elle permet d'implémenter des applis simples « à la Elm » tout en restant dans l'écosystème Haskell. En revanche, son environnement est moins mature : les outils Ghcjs + Miso + Nix ne sont pas complètement triviaux à mettre en place et les temps d'installation d'installation et de compilation plus longs.
Haskell/Reflex
Reflex est une bibliothèque Haskell de FRP générique. Elle est complétée par des projets associés : reflex-dom (DOM virtuel), reflex-platform (système de compilation multi-plateforme)… Une application Reflex peut être compilée avec Ghc ou avec Ghcjs et ainsi produire des applications web ou natives (PC ou mobile).
Ci-dessous une implémentation en Haskell + Reflex de l’application d’exemple. Contrairement aux implémentations précédentes, ce code ne suit pas une architecture MVC mais gère explicitement les éléments graphiques et leurs flux d'événements. Il est tout à fait possible d'organiser le code selon un MVC mais ceci est à la charge du programmeur.
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
import Data.Aeson (FromJSON)
import Data.Default (def)
import Data.Maybe (fromJust)
import Data.Monoid ((<>))
import Data.Text (Text)
import GHC.Generics (Generic)
import Prelude
import Reflex (holdDyn)
import Reflex.Dom
import Reflex.Dom.Xhr (decodeXhrResponse, performRequestAsync, XhrRequest(..))
main :: IO ()
main = mainWidget ui
-- Model
data Animal = Animal
{ animalType :: Text
, animalImage :: Text
} deriving (Eq, Generic, Show)
instance FromJSON Animal
-- View / Controler
ui :: MonadWidget t m => m ()
ui = do
el "h1" $ text "Animals (Reflex)"
myInput <- el "p" $ textInput def
evStart <- getPostBuild
let evs = [ () <$ _textInput_input myInput , evStart ]
let evCode = tagPromptlyDyn (value myInput) (leftmost evs)
evResponse <- performRequestAsync $ queryAnimals <$> evCode
let evResult = fromJust . decodeXhrResponse <$> evResponse
dynAnimals :: (Dynamic t [Animal]) <- holdDyn [] evResult
_ <- el "span" $ simpleList dynAnimals displayAnimal
return ()
queryAnimals :: Text -> XhrRequest ()
queryAnimals code = XhrRequest "GET" ("http://localhost:3000/api/animals/" <> code) def
displayAnimal :: MonadWidget t m => Dynamic t Animal -> m ()
displayAnimal dynAnimal = do
let imgSrc = (<>) "http://localhost:3000/img/" . animalImage <$> dynAnimal
let imgAttrs0 = ("width" =: "320") <> ("height" =: "240")
let imgAttrs = ((<>) imgAttrs0) . (=:) "src" <$> imgSrc
el "div" $ do
el "p" $ dynText $ animalType <$> dynAnimal
elDynAttr "img" imgAttrs $ dynText imgSrc
Reflex est un projet assez ambitieux, censé permettre de développer tout type d'interfaces utilisateur et pour de nombreuses plateformes différentes. Il a l'avantage d'utiliser le langage Haskell. En revanche, il est assez compliqué à prendre en main. Programmer directement en FRP nécessite un vrai apprentissage ainsi qu'une bonne compréhension des foncteurs, applicatives et monades. Enfin, il faut structurer son code soigneusement mais soi-même.
Conclusion
Elm, Purescript, Miso et Reflex permettent de développer des applis web tout en profitant des avantages de la programmation fonctionnelle. Ces outils facilitent effectivement la validation de code et le refactoring, et réduisent voire suppriment les erreurs au runtime.
Le principal inconvénient réside dans le choix parmi ces outils, qui nécessite de faire un compromis entre simplicité et flexibilité. Elm et Purescript sont de bonnes options pour du web « pur et dur ». Miso et Reflex sont plutôt à réserver à des développeurs Haskell expérimentés.
Enfin, en dehors d'Haskell, il peut être intéressant de considérer d'autres outils comme ClojureScript, Ocsigen…
# MVC
Posté par barmic . Évalué à 6.
Je ne me suis pas penché sur les autres que je ne connais pas, mais ELM n'implémente pas MVC.
Le contrôleur de MVC manipule le modèle souvent, le modèle est représenté par les données membres d'une classe contrôleur. Le contrôleur possède l'état, on appel l'une de ses méthode et il modifie l'état. Ici l'Update va prendre l'état courant en paramètre + un message qui est généré par la vue et il va en ressortir un nouvel état (+ éventuellement un message). L'Update ne possède pas l'état, c'est quelque chose qui lui est donné en paramètre et qu'il ne peux pas modifier. Un paquet de frameworks MVC obligent la vue à passer par le contrôler pour accéder au modèle (c'est lui qui le possède), alors que dans cet architecture ça n'est pas le cas.
Ça paraît anodin mais conceptuellement c'est très différent et ça a pas mal d'impacts.
[^] # Re: MVC
Posté par nokomprendo (site web personnel) . Évalué à 4.
Ce que tu décris est une implémentation classique d'un MVC en POO, mais un MVC ne peut pas s'implémenter comme ça en programmation fonctionnelle. D'autre part, pour le web frontend, l'aspect asynchrone est important et c'est pour cela qu'on utilise souvent des MVC unidirectionnels. Le MVC n'a pas vraiment de définition rigoureuse. Elm parle effectivement de Model-View-Update https://guide.elm-lang.org/architecture/ et chaque framework propose sa variante (MVP, MVE, MVVM, MVW…). Ici, j'ai préféré utiliser MVC dans un sens un peu général.
[^] # Re: MVC
Posté par barmic . Évalué à 2. Dernière modification le 20 août 2018 à 21:54.
Ben je pense que c'est vraiment plus à rapprocher de l'architecture Flux décrit par Facebook. Il n'y a pas de binding du model dans la vue. L'objectif c'est que la donnée a un chemin unidirectionnelle. En tout cas c'est pour ça que Flux a était créé.
# Article sympa a lire
Posté par F(log) . Évalué à 4.
Merci pour cet article et comparaison, sympa a lire.
Quelle est la solution la plus simple pour faire une application mobile venant du ELM/Haskell?
Je souhaiterai avoir le ressenti d'un développeur Haskell avec Reflex, et si ça vaut le coup pour faire des applications mobiles?
Quelques typos:
- les applitions natives // applications
- des applition web // applications
- on définit également un type Animals // Animal
Question de curiosite, immuabilité et immutabilité font référence au mème concept?
[^] # Re: Article sympa a lire
Posté par nokomprendo (site web personnel) . Évalué à 4.
Je n'ai aucune expérience dans le mobile mais apparemment ça fait partie des objectifs de Reflex. Le projet Reflex-platform permet de compiler pour du natif, du web, android et ios (https://github.com/reflex-frp/reflex-platform/blob/develop/docs/project-development.md). Perso, je trouve que Reflex n'est pas complètement trivial et qu'il faut prévoir un peu de temps pour l'apprendre correctement, mais Reflex-platform peut aussi compiler du Miso; c'est peut-être un bon compromis (https://github.com/dmjio/miso/issues/367).
Pour immuable/immutable, oui c'est le même concept. Je crois que ce sont vraiment des synonymes mais immutable, ça fait un peu anglicisme.
[^] # Re: Article sympa a lire
Posté par Guillaum (site web personnel) . Évalué à 7.
Hello,
Pour ma part je ne suis absolument pas du tout du web / application mobile, alors le jour ou j'ai du en réaliser une, j'ai cherché comment faire en Haskell ;)
J'ai fais ça pour ma femme: https://github.com/guibou/givorsDays
J'ai utilisé Reflex et, une fois le setup de reflex-plateform effectué, c'est très agréable. Ce qui est vraiment fort c'est de pouvoir develloper sur son ordinateur en testant dans son navigateur, avec un rebuild instantané, et d'avoir l'application mobile qui sort automatiquement après.
La façon de programmer de Reflex (i.e. le "Reactive programming") est très agréable à utiliser quand je compare au plat de nouille que j'aurais pu faire si je l'avais fais en mode evénement / callback. Ceci est à prendre avec des pincettes, car ce n'est pas du tout mon domaine de prédilection.
Les plus de
Reflex
, de mon point de vu limité :Event
est une instance deFunctor
, doncmap
fonctionne dessus.Les moins:
Reflex.Dom
c'est du web, donc il faut à minima y comprendre quelque chose en mise en page avec des CSS. Il y a quelques libraries (comme Clay: http://fvisser.nl/clay/) qui permettent d'éditer facilement du CSS, mais je me suis vraiment perdu dans ces histoire deflex
outable
ou autre. Une personne habituée au CSS n'aura pas ce problème. On doit aussi pouvoir utiliser des librairies de layout toute prêtes, mais je n'y connais rien.# réinvention de la roue
Posté par niuxe . Évalué à -6. Dernière modification le 27 août 2018 à 11:27.
Quel est l'intérêt de ces outils (Elm, Purescript, Miso et Reflex) ? aucun !
[^] # Re: réinvention de la roue
Posté par barmic . Évalué à 6.
Wow du calme :)
Mis à par Vanilla JS aucune lib ni framework front web n'est standard.
C'est ton avis.
Non. Déjà tu mélange vraiment beaucoup de choses… React et Vue sont des techno de vue uniquement, donc ils ne se placent pas en alternative. Et aucune des autres techno dont tu parle n'implémente véritablement de patern réactif. Tu aurais parlé de redux, vuex ou ngrx tu aurais déjà gardé un peu plus de crédibilité. Bon pour le coup ELM est celui qui a inspiré ces framework donc…
Mais même sans être arrivé avant. ELM (je parle de celui que je connais) vient avec un ensemble assez cohérent de fonctionnalités. Redux te dis de ne jamais muter ton état, mais pour le faire soit il dois te faire confiance soit passer par des bibliothèques pour faire ça. Elles font un peu comme elles peuvent là où un compilateur va assurer dans une phase avant même l'exécution (ELM a une étape de compilation vers JS). Son système de type lui permet aussi de garantir que certaines classes d'erreur ne peuvent pas exister par construction. Là où dans des langages ayant un système de type moins puissant c'est impossible.
Pour les perf je n'en sais rien, mais pour le résultat, c'est possible mais pas facile. T'assurer que tu n'a aucune erreur de type en JS ça n'est pas possible quelque soit le nombre que tu accole à ES.
Ils simplifient fortement l'implémentation d'une architecture réactive/flux dans les applications web. Ce sont aussi des langages plus sûr que JS.
# Projet de réalisation d'un site internet utilisant ces technologies.
Posté par Serge Leblanc . Évalué à 0.
J'envisage d'utiliser ces technos pour réaliser un site de prise de décision par émergence de consensus.
Ce site permettra à chaque participant (d'un Conseil d'Administration d'une Scop ou d'association, par exemple) d'émettre des propositions et suggestions dans une sorte de forum (une agora) et d'ordonner préférentiellement celles-ci.
Par la méthode de Condorcet de ce rangement émerge le consensus et fait office de vote.
Je développe en Agda mais ne maitrisant pas suffisamment Haskell pour me lancer seul dans un tel projet, toute aide sera bienvenue.
Si vous souhaitez plus de précisions ou que cela vous intéresse, merci de me contacter :
Serge Leblanc 33dbqNxPy7IF@gmail.com
GnuPG --fingerprint : 2B2D AC93 8620 43D3 D2C2 C2D3 B67C F631 67B1 7A3F
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.